# -*- coding: utf-8 -*-
import scrapy
import re
import urllib.request
from copy import deepcopy


class SuningSpider(scrapy.Spider):
    name = 'suning'
    allowed_domains = ['suning.com']
    start_urls = ['https://book.suning.com/?safp=d488778a.homepage1.99345513004.47'] #能否成为我们起始的url地址，是根据它所得到的响应Network-response是否包含我们想要的数据

    def parse(self, response):
        #1.大分类
        div_list = response.xpath('//div[@class="left-menu-container"]/div/div[@class="menu-item"]')
        for div in div_list:
            item = {}
            item["superclass"] = div.xpath('./dl/dt/h3/a/text()').extract_first() #是dL不是d1(数字)
            # print(item)
            a_list = div.xpath('./dl/dd/a') #是dL不是d1(数字)
            # print(a_list)
            #2.小标签分组
            for a in a_list:
                item["subclass"] = a.xpath('./text()').extract_first()
                item["sub_href"] = a.xpath('./@href').extract_first()
                # print(item)
                if item["sub_href"] is not None:
                    yield scrapy.Request(
                        item["sub_href"],
                        callback=self.book_list,
                        meta={"item":deepcopy(item)} #下一个解析函数中的item不会和这个item相互影响
                    )
    def book_list(self,response):
        item = deepcopy(response.meta["item"])
        #3.图书列表页分组
        li_list = response.xpath('//div[@class="filter-results productMain clearfix  temporary"]/ul/li')
        for li in li_list:
            item["book_name"] = li.xpath('.//div[@class="res-info"]/p[@class="sell-point"]/a/text()').extract_first()
            item["book_img"] = "https:" + li.xpath('//div[@class="img-block"]/a/img/@src2').extract_first()    #这里要根据response来（src2），而不是elements（src）
            item["shop_name"] =  li.xpath('.//div[@class="res-info"]/p[@class="seller oh no-more "]/a/text()').extract_first()
            item["book_href"] = "https:" + li.xpath('.//div[@class="res-info"]/p[@class="sell-point"]/a/@href').extract_first()
            #4.进入图书详情页
            yield scrapy.Request(
                item["book_href"],
                callback=self.book_detail,
                meta = {"item":response.meta["item"]} #洁癖写法
            )

        #4.翻页（ajax请求，整个url地址没有变化，但是内容刷新了）
        # 稍稍往response下翻一下，得出当前页面和总页数
        currentPage = int(re.findall('param.currentPage = "(.*?)";',response.body.decode())[0])  #注意中英文括号
        totalPage = int(re.findall('param.pageNumbers = "(.*?)";', response.body.decode())[0])
        if currentPage < totalPage:
            if currentPage == 0:
                pageUrl = response.url
                pat1 = '1-(.*?)-0'
                """
                注意：<a name="pindao_book_27532174_word02" target="_blank" href="https://list.suning.com/1-502890-0-0-0-0.html">美食</a>
                其对应的Request URL: https://list.suning.com/emall/showProductList.do?ci=502890&pg=03&cp=1
                """
                key_id = re.findall(pat1, pageUrl)
                pat2 = 'search.suning.com/(.*?)/'
                keyword = re.findall(pat2, pageUrl)
                if len(key_id) != 0:
                    nextUrl = "https://list.suning.com/emall/showProductList.do?ci=" + key_id[0] + "&pg=03&cp=" + str(currentPage+1)
                    print("下一页的地址：" + nextUrl)
                    yield scrapy.Request(
                        nextUrl,
                        callback=self.book_list,
                        meta={"item": response.meta["item"]}
                    )
                elif len(keyword) != 0:
                    nextUrl = "https://search.suning.com/emall/searchV1Product.do?keyword=" + keyword[0] + "&ci=0&pg=01&cp="+ str(currentPage+1)
                    print("下一页的地址：" + nextUrl)
                    yield scrapy.Request(
                        nextUrl,
                        callback=self.book_list,
                        meta={"item": response.meta["item"]}
                    )
            else:
                pageUrl = response.url
                pat3 = '(.*cp=)'
                nextUrl2 = re.compile(pat3).findall(pageUrl)[0] + str(currentPage+1)
                print("下一页的地址：" + nextUrl2)
                yield scrapy.Request(
                    nextUrl2,
                    callback=self.book_list,
                    meta={"item": response.meta["item"]}
                )

        else:
            print("已经是最后一页（没有下一页）！！！")
        """
        也可以这么写：（非强迫症写法）
        item = response.meta["item"]
        .....
        meta = {"item":item}
        """

    def book_detail(self,response):
        item = response.meta["item"]
        #这里不能使用li的顺序来定位，有的没有作者！只有两个li标签
        item["author"] = response.xpath('//div[@class="proinfo-main"]/ul/li/span[text()="作者："]/../text()').extract_first()    #//text()才能取到“作者”两个字，/text()只能取到“作者”的内容
        #注意，如果item["author"] = None 使用re.sub方法会报错，因为None值不是字符串
        if item["author"] is not None:
            item["author"] = re.sub(r"\r|\n|\t|\s","",item["author"])   #去除很多无用的，包括空白字符
        else:
            item["author"] = "无作者信息"
        item["press"] = response.xpath('//div[@class="proinfo-main"]/ul/li/span[text()="出版社："]/../text()').extract_first()
        if item["press"] is not None:
            item["press"] = re.sub(r"\r|\n|\t|\s","",item["press"])
        else:
            item["press"] = "无出版社信息"
        item["publish_date"] = response.xpath('//div[@class="proinfo-main"]/ul/li/span[text()="出版时间："]/../span[2]/text()').extract_first()
        #获取价格
        book_url = response.url
        pat1 = 'suning.com/(.*?)/'
        id_1 = re.compile(pat1).findall(book_url)[0]
        pat2 = '\d/(.*?).html'
        id_2 = re.compile(pat2).findall(book_url)[0]
        #构造获取价格的网址
        if len(id_2) == 11:
            price_url = "https://pas.suning.com/nspcsale_0_0000000"+id_2+"_0000000"+id_2+"_"+id_1+"_250_029_0290199_502282_1000257_9254_12006_Z001___R9011195_0.2___.html?"
        elif len(id_2) == 9:
            price_url = "https://pas.suning.com/nspcsale_0_000000000"+id_2+"_000000000"+id_2+"_"+id_1+"_250_029_0290199_502282_1000257_9254_12006_Z001___R9011195_0.2___.html?"
        else:
            print("特殊网址！！！")
        data = urllib.request.urlopen(price_url).read().decode('utf-8','ignore')
        price_pat = '"netPrice":"(.*?)"'
        item["price"] = re.compile(price_pat).findall(data)[0]
        print(item)

""""""
"""
注意1：<ul class="clearfix">...</ul>，功能：清除样式——html代码中会有很多，所以不要使用它定位

注意2：注意传递“值”，而不能传递“地址”
    核心问题1：
        都在scrapy框架下，
            之前的for li 循环没有出现后一次的items属性值覆盖前一次的情况是因为，当时一个item就只对应一个对象（一条信息）
            但是，这里这里存在多个分组——几个item共享一个大分类，几个解析函数之间会相互影响
    核心问题2：
        scrapy是多线程的，request是单线程的
    解决方法：使用copy.deepcopy
    类似：同一个程序的多个快捷方式，但是非安装直接可以使用的软件不一样（各自独立，不能同时打开）
        
注意3：苏宁做了反爬处理，即不会把一些重要信息（价格）直接作为response返回，而且在网页加载结束之后，通过js在将对应的值赋值上去。

注意4：翻页ajax请求，在当前访问的url地址中没有想要的下一页的地址（空的），而是通过json文件生成的
"""
